#include <math.h>
#include <stdlib.h>
#include <time.h>

//////// Original, simple variant
//#define SALT 1034871905
//char charset[] = "0123456789abcdefghijklmnopqrstuvwxyz";
//#define CHARSET_LENGTH 36
//#define HASH_LENGTH 6
/////////////////////////////////////////////////////////////



//char charset[] = "qp2a5zm7ws3kx4yed6jcnr9ufihv8btg";
char charset[] = "EqPpW2aH5zSm7wGs3kx4yMeRd6KjVcNnr9JuYfXiThDLv8bAtg";
//no l, no 1, no O, no 0 - to not to confuse users (NB! i is present)


#define CHARSET_LENGTH ((sizeof charset) - 1)
#define HASH_LENGTH ((unsigned int)3)
#define NOISE_LENGTH 5

#define PASSWORD_LENGTH ((unsigned int) HASH_LENGTH + NOISE_LENGTH)

//keyspace: 1 073 741 824 different combinations
//#define SALT ((unsigned int)925173854)
#define SALT 39219

void noise(char *);

void hash(unsigned int plain, char *_hash)
{
	unsigned int temp;
	
	plain += SALT;

	for(int i=HASH_LENGTH-1; i>=0; i--)
	{
		unsigned int deg = (unsigned int) pow((double)CHARSET_LENGTH, (int)i);
		temp = plain / deg;
		_hash[HASH_LENGTH-1-i] = charset[temp];
		plain -= temp*deg;
	}

}

void hash2(unsigned int plain, char *_hash)
{
	noise(_hash);
	hash(plain, _hash + NOISE_LENGTH);	
}

int getindex(char c, char *_charset)
{
	int i;
	int l = CHARSET_LENGTH;
	for (i=0; i<CHARSET_LENGTH; i++)
	{
		if (charset[i] == c) return i;
	}

	return -1;
}

unsigned int dehash(char *hash)
{
	unsigned int result = 0;
	int temp;

	for (int i=0; i<HASH_LENGTH; i++)
	{
		temp = getindex(hash[i], charset);
		if (-1 == temp) return -1;
		result += temp * (unsigned int)(pow((double)CHARSET_LENGTH, (int)(HASH_LENGTH-1-i)));
	}
	
	result -= SALT;
	return result;
}

unsigned int dehash2(char * _hash)
{
	return dehash(_hash + NOISE_LENGTH);
}

void noise(char *noise)
{
	static bool seeded = false;
	if (!seeded)
	{
		long t = time(NULL);
		srand( (unsigned) t );
		seeded = true;
	}

	int temp = 0;
	for (int i = 0; i< NOISE_LENGTH; i++)
	{
		temp = rand();
		noise[i] = charset[temp % CHARSET_LENGTH];
	}
}
